/**
* \file
* \author  Jon Ove Storhaug <jostorha@gmail.com>
* \version 0.1
* \brief jospos 
*
* \section LICENSE
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details at
* http://www.gnu.org/copyleft/gpl.html
*
* \section DESCRIPTION
*
*/
#include <stdlib.h>
#include <avr/io.h>
#include "global.h"
#include "uart.h"
#include <avr/interrupt.h>	// include interrupt support
#include "i2c.h"			// include i2c support
#include "ds1631.h"			// include DS1631 support
#include "lcd.h"
#include <util/delay.h>
#include <string.h>
#include <stdio.h>
#include <avr/wdt.h>
#include "onewire.h"
#include "ds18x20.h"


#define BAUD 4800

#define NMEAID 		0
#define NMEATIME 	1
#define NMEALAT 	2
#define NMEALAT2 	3
#define NMEALONG 	4
#define NMEALONG2 	5
#define NMEAFIX 	6
#define NMEASAT 	7
#define NMEAHDOP 	8
#define NMEAALT 	9
#define NMEAHGTWGS 	10
#define NMEAUPDTTM 	11
#define NMEADGPSREF 12
#define NMEACHKSUM 	13


// --- onewire sensors
#define MAXOWSENSORS 1
static uint8_t gOWSensorIDs[MAXOWSENSORS][OW_ROMCODE_SIZE];
static int16_t gOWTempdata[MAXOWSENSORS]; // temperature times 10
static int8_t gOWsensors=0;
static uint8_t gOWTemp_measurementstatus=0; // 0=ok,1=erro
static volatile uint8_t gMeasurementTimer=0; // sec
static volatile uint8_t gSec=0;
uint8_t gAllSensorsReadOnce=0;

//! Disables the watchdog timer
///
void get_mcusr(void) \
__attribute__((naked)) \
__attribute__((section(".init3")));

//! Init the temperature sencor, DS1621 or DS1631
///
void ds1631init(void);

//! Read the temperature sencor
///
void ds1631getTemp(void);

void nmea_parse(unsigned char *nmeadata, unsigned char **nmea_str);
void NMEAEdit(unsigned char nmea_str[][15]);

void onewire_read_temp_meas(void);
void onewire_start_temp_meas(void);
int8_t onewire_search_sensors(void);
int8_t roundanddivide(int16_t val);
ISR(PCINT0_vect);
ISR(PCINT1_vect);

uint8_t mcusr_mirror;
signed char temp;
unsigned char backlight = 0;
button0Flag=0;
button1Flag=0;
button0Counter=0;
button1Counter=0;
FILE uart_str = FDEV_SETUP_STREAM(uartSendByte, uartGetByte, _FDEV_SETUP_RW);
FILE lcd_str = FDEV_SETUP_STREAM(lcdDataWrite, NULL, _FDEV_SETUP_WRITE);


int main(void)
{
	//get_mcusr();
	CLKPR=0x80;
	CLKPR=0x00;
	DDRB=0xff; //PORTB is output
	DDRD = 0x12; 
	PORTD = 0xff; // Set all outputs high and enable pullup on all inputs
	PORTD &= ~0x20;
	uartInit();
	uartSetBaudRate(BAUD);
	stdout = stdin = &uart_str;
	stderr = &lcd_str;
	_delay_ms(2000);
	//ds1631init();	
	lcdInit();
	printf("MCU starting");
	fprintf(stderr,"0123456789012345678998765432109876543210705");
	
	//wdt_enable(WDTO_8S);
	//wdt_reset();
	gOWsensors=onewire_search_sensors();
	unsigned char c='0';
	unsigned char nmeaP[140];
	unsigned char nmea_str[15][15];
	int counter=0;
	//PCMSK0 |= (1<<PIND2);		
	// The rising edge of INT1 generates an interrupt request.
	EICRA |= 0x0e; // The falling edge of INT0 generates an interrupt request.
	EIMSK |= 0x03; // Enable External Interrupt Request 0 and 1
	EIFR &= ~0x03; // Clear External Interrupt Flag 0 and 1
	
	
	// Set Pin 6 (PD2) as the pin to use for this example
	//PCMSK |= (1<<PIND2);
	
	// interrupt on INT0 pin falling edge (sensor triggered) 
	//MCUCR = (1<<ISC01) | (1<<ISC00);
	
	// turn on interrupts!
	//GIMSK  |= (1<<INT0);
	
	// 	for (int i=0; i<16; i++)
	// 	{
		// 	   for (int j=0; j<16; j++)
		// 	   {
			// 	      nmea_str[i][j]='\0';
			// 	   }
			// 	}
			lcdClear();
			while(1)
			{	
				if (button0Flag)
				{
					if (backlight)
					{
						PORTD &= ~0x20;
						backlight = 0;
					}
					else
					{
						PORTD |= 0x20;
						backlight=1;
					}
					button0Flag = 0;
					
				}
				char switches = PIND;
				switches |= ~0x04;
				if (switches == -5) //find out why -5 when pressed and 1 when not!!!
				{
					button0Counter++;
					//fprintf(stderr,"%d",button0Counter);
				}
				else
					button0Counter=0;
				//fprintf(stderr,"%d",switches);
				if (button0Counter>10)
					//@TODO: Display Turning off message
					PORTD = 0x00;
					
				//uartFlushReceiveBuffer();
				while (uartReceiveBufferIsEmpty())
					;;
				
				//while (c != '$')
				//{
					//	uartReceiveByte(&c);
					//}
					
					//_delay_ms(1500);
					counter=0;
					//uartReceiveByte(&c);
					while(c!='$')
						uartReceiveByte(&c);			
					if(c=='$')
					{
						//fprintf(stderr,"1 ");
						while (uartReceiveBufferIsEmpty())
							;;
						uartReceiveByte(&c);
						counter=0;
					}
					//fprintf(stderr,"%c",c);
					while (c!='$')
					{
						//fprintf(stderr,"3");
						nmeaP[counter]=c;
						counter++;
						while (uartReceiveBufferIsEmpty())
							;;
						uartReceiveByte(&c);
						//fprintf(stderr,"%c",c);
					}
					//_delay_ms(1000);
					//lcdClear();
					nmeaP[counter]='\0';	
					//fprintf(stderr,"4");
					//lcdHome(); 
					//fprintf(stderr,"%s",nmeaP);
					//fprintf(stderr,"hei");
					
					//fprintf(stderr,"%c",nmeaP[0]);
					//fprintf(stderr,"%c",nmeaP[1]);
					//fprintf(stderr,"%c",nmeaP[2]);
					//fprintf(stderr,"%c",nmeaP[3]);
					//fprintf(stderr,"%c",nmeaP[4]);
					//_delay_ms(3000);
					//
					// we need the measurementstate otherwise we would
					// execute the same thing serveral times in that second
					//if (measurementstate==0){
   //	//s_connectionreset(sensor);
   //	//LEDON;
   //	measurementstate++;
   //}
   //if (measurementstate==1){
   //	//gSensorErrors[sensor]=s_measure(MEASURE_TEMP,sensor); //measure temperature
   //	// for onewire DS18X20 sensors we need just
   //	// under 1sec between starting and reading
   //	// of measurements:
   //	onewire_start_temp_meas();
   //	measurementstate++;
   //	
   //	if (measurementstate==2) {
   //		// now poll sensor until it is ready
   //		// might take up to 220ms
   //		//if (s_resultready(sensor)){
   //		//		gSensorErrors[sensor]=s_readmeasurement( &gTempval_raw[sensor],sensor); 
   //		measurementstate=0;
   //		//if (gSensorErrors[sensor]!=0){
   //		//				measurementstate=5;
   //		//		}
   //		//}
   //	}
   //	onewire_read_temp_meas(); 
   //	
   //	//
   //}	
   //
   
   
   
   if(nmeaP[0]=='G'&&nmeaP[1]=='P'&&nmeaP[2]=='G'&&nmeaP[3]=='G'&&nmeaP[4]=='A')
   {
	   //_delay_ms(1000);
	   static int temperature=0;
	   onewire_start_temp_meas();
	   //_delay_ms(1000);
	   onewire_read_temp_meas();
	   //_delay_ms(1000);
	   
	   if (gOWTempdata[0]!=999)
		   temperature = roundanddivide(gOWTempdata[0]);
	   //	lcdClear();
	   lcdGotoXY(0,2);
	   fprintf(stderr,"%d",temperature);
	   //fprintf(stderr,"%d%sC",temperature,0x0c);//gOWTempdata[0]);//temperature);//temperature);
	   
	   
	   //fprintf(stderr,"JA");
	   //nmea_parse(nmeaP, nmeaStr);
	   
	   unsigned char i,j=0,k=0;
	   for(i=0;nmeaP[i]!='\r';i++)
	   {
		   if(nmeaP[i]==',')
		   {
			   nmea_str[j][k]='\0';
			   j++;
			   k=0;
		   } 
		   else 
		   {
			   nmea_str[j][k] = nmeaP[i];
			   k++;
		   }
	   }
	   NMEAEdit(nmea_str);
	   
	   lcdGotoXY(12,0);
	   fprintf(stderr,"%s",nmea_str[NMEATIME]);
	   lcdGotoXY(15,1);
	   fprintf(stderr,"%s",nmea_str[NMEASAT]);
	   lcdGotoXY(1,0);
	   fprintf(stderr,"%s",nmea_str[NMEALAT]);
	   fprintf(stderr,"%s",nmea_str[NMEALAT2]);
	   lcdGotoXY(0,1);
	   fprintf(stderr,"%s",nmea_str[NMEALONG]);
	   fprintf(stderr,"%s",nmea_str[NMEALONG2]);
	   lcdGotoXY(0,3);
	   fprintf(stderr,"%s",nmea_str[NMEAALT]);
	   
	   //fprintf(stderr,"%s",nmea_str[NMEALONG2]);
	   
   }
   //fprintf(stderr,"hei");
   
   //lcdClear();
   
   //gpsInfoPrint();
   //fprintf(stderr,"%c",c);
   //wdt_reset();
   
			}
			
			return 0;
		}
		
		void ds1631init(void)
		{
			// initialize i2c function library
			i2cInit();
			i2cSetBitrate(100);
			// initialize
			ds1631Init(DS1631_I2C_ADDR);
			// set config
			ds1631SetConfig(DS1631_I2C_ADDR, 0x0F);
			// set the temperature limit registers
			ds1631SetTH(DS1631_I2C_ADDR, 35<<8);
			ds1631SetTL(DS1631_I2C_ADDR, 30<<8);	
		}
		
		void ds1631getTemp(void)
		{
			s16 T=0;	
			// start convert
			ds1631StartConvert(DS1631_I2C_ADDR);
			// wait until done
			while(!(ds1631GetConfig(DS1631_I2C_ADDR) & DS1631_CONFIG_DONE));
			// Read temp
			T = ds1631ReadTemp(DS1631_I2C_ADDR);
			temp=T>>8; // The temperature is saved to temp, no decimals, just the integer
		}
		
		void get_mcusr(void)
		{
			mcusr_mirror = MCUSR;
			MCUSR = 0;
			wdt_disable();
		}
		
		void nmea_parse(unsigned char *nmeadata, unsigned char **nmea_str)
		{
			unsigned char i,j=0,k=0;
			for(i=0;nmeadata[i]!='\r';i++){
				if(nmeadata[i]==','){
					j++;
					k=0;
				} else {
					nmea_str[j][k] = nmeadata[i];
					k++;
				}
			}
		}
		
		void NMEAEdit(unsigned char nmea_str[][15])
		{	
			nmea_str[NMEATIME][8]='\0';
			nmea_str[NMEATIME][7]=nmea_str[NMEATIME][5];
			nmea_str[NMEATIME][6]=nmea_str[NMEATIME][4];
			nmea_str[NMEATIME][5]=':';
			nmea_str[NMEATIME][4]=nmea_str[NMEATIME][3];
			nmea_str[NMEATIME][3]=nmea_str[NMEATIME][2];
			nmea_str[NMEATIME][2]=':';
			nmea_str[NMEATIME][1]=nmea_str[NMEATIME][1];
			nmea_str[NMEATIME][0]=nmea_str[NMEATIME][0];
			
			
			nmea_str[NMEALAT][10]='\0';
			nmea_str[NMEALAT][9]=0x27; // apostrophe (minute sign)
			nmea_str[NMEALAT][8]=nmea_str[NMEALAT][7];
			nmea_str[NMEALAT][7]=nmea_str[NMEALAT][6];
			nmea_str[NMEALAT][6]=nmea_str[NMEALAT][5];
			nmea_str[NMEALAT][5]=nmea_str[NMEALAT][4];
			nmea_str[NMEALAT][4]=nmea_str[NMEALAT][3];
			nmea_str[NMEALAT][3]=nmea_str[NMEALAT][2];
			nmea_str[NMEALAT][2]=0x0c; // custom char degree, could have used non custom char 0xdf instead
			nmea_str[NMEALAT][1]=nmea_str[NMEALAT][1];
			nmea_str[NMEALAT][0]=nmea_str[NMEALAT][0];
			
			nmea_str[NMEALONG][11]='\0';
			nmea_str[NMEALONG][10]=0x27; // apostrophe (minute sign)
			nmea_str[NMEALONG][9]=nmea_str[NMEALONG][8];
			nmea_str[NMEALONG][8]=nmea_str[NMEALONG][7];
			nmea_str[NMEALONG][7]=nmea_str[NMEALONG][6];
			nmea_str[NMEALONG][6]=nmea_str[NMEALONG][5];
			nmea_str[NMEALONG][5]=nmea_str[NMEALONG][4];
			nmea_str[NMEALONG][4]=nmea_str[NMEALONG][3];
			nmea_str[NMEALONG][3]=0x0c; // custom char degree, could have used non custom char 0xdf instead
			nmea_str[NMEALONG][2]=nmea_str[NMEALONG][2];
			nmea_str[NMEALONG][1]=nmea_str[NMEALONG][1];
			nmea_str[NMEALONG][0]=nmea_str[NMEALONG][0];
		}
		// read the latest measurement off the scratchpad of the ds18x20 sensor
		// and store it in gOWTempdata
		void onewire_read_temp_meas(void){
			uint8_t i;
			uint8_t subzero, cel, cel_frac_bits;
			for ( i=0; i<gOWsensors; i++ ) {
				
				if ( DS18X20_read_meas( &gOWSensorIDs[i][0], &subzero,
					&cel, &cel_frac_bits) == DS18X20_OK ) {
					gOWTempdata[i]=cel*10;
				gOWTempdata[i]+=DS18X20_frac_bits_decimal(cel_frac_bits);
				if (subzero){
					gOWTempdata[i]=-gOWTempdata[i];
				}
				}else{
					gOWTempdata[i]=999;
				}
			}
		}
		
		// start a measurement for all sensors on the bus:
		void onewire_start_temp_meas(void){
			gOWTemp_measurementstatus=0;
			if ( DS18X20_start_meas(NULL) != DS18X20_OK) {
				gOWTemp_measurementstatus=1;
			}
		}
		
		// writes to global array gOWSensorIDs
		int8_t onewire_search_sensors(void)
		{
			uint8_t diff;
			uint8_t nSensors=0;
			for( diff = OW_SEARCH_FIRST; 
			diff != OW_LAST_DEVICE && nSensors < MAXOWSENSORS ; )
			{
				DS18X20_find_sensor( &diff, &(gOWSensorIDs[nSensors][0]) );
				
				if( diff == OW_PRESENCE_ERR ) {
					return(-1); //No Sensor found
				}
				if( diff == OW_DATA_ERR ) {
					return(-2); //Bus Error
				}
				nSensors++;
			}
			return nSensors;
		}
		// convert a value times 10 into value and round it
		// Example: -206 becomes -21, 306 becomes 31, 103 becomes 10.
		int8_t roundanddivide(int16_t val){
			if (val<0){
				return((val-5)/10);
			}
			return((val+5)/10);
		}
		
		ISR(INT0_vect)
		{
			button0Flag=1;
		}
		
		
		ISR(INT1_vect)
		{
			button1Flag=1;
			//EIFR &= ~0x03; // Clear External Interrupt Flag 0 and 1
			
		}
		